// ==UserScript==
// @name         API监控库
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  通用的接口监控库，可被其他脚本引用
// @author       You
// @grant        GM_addStyle
// ==/UserScript==

(function() {
    'use strict';

    // 防止重复加载
    if (window.APIMonitorLib) {
        console.log('[API监控库] 库已存在，跳过加载');
        return;
    }

    // 日志工具函数
    function log(message, type = 'info', prefix = 'API监控库') {
        const timestamp = new Date().toLocaleString('zh-CN');
        const logMessage = `[${prefix} ${timestamp}] ${message}`;
        
        switch(type) {
            case 'error':
                console.error(logMessage);
                break;
            case 'warn':
                console.warn(logMessage);
                break;
            case 'success':
                console.log(`%c${logMessage}`, 'color: green; font-weight: bold;');
                break;
            default:
                console.log(`%c${logMessage}`, 'color: blue;');
        }
    }

    // 存储接口返回数据的全局变量
    window.APIMonitorData = {
        responses: {},
        lastUpdate: null,
        config: {
            maxStorage: 100, // 最大存储数量
            enableLog: true, // 是否启用日志
            filterUrls: [], // 过滤的URL
            includeUrls: [] // 只包含的URL
        },
        requestInterceptor: null // 请求拦截器
    };

    // 存储接口响应数据
    function storeApiResponse(url, method, response, status) {
        // 检查URL过滤 - 如果设置了过滤列表，则跳过匹配的URL
        if (window.APIMonitorData.config.filterUrls.length > 0) {
            if (window.APIMonitorData.config.filterUrls.some(filter => url.includes(filter))) {
                return;
            }
        }
        
        // 检查包含列表 - 如果设置了包含列表，则只监控匹配的URL
        // 如果包含列表为空，则监控所有URL
        if (window.APIMonitorData.config.includeUrls.length > 0) {
            if (!window.APIMonitorData.config.includeUrls.some(include => url.includes(include))) {
                return;
            }
        }

        const key = `${method}_${url}`;
        window.APIMonitorData.responses[key] = {
            url: url,
            method: method,
            response: response,
            status: status,
            timestamp: new Date().toISOString()
        };
        window.APIMonitorData.lastUpdate = new Date().toISOString();
        
        // 限制存储数量
        const keys = Object.keys(window.APIMonitorData.responses);
        if (keys.length > window.APIMonitorData.config.maxStorage) {
            const oldestKey = keys[0];
            delete window.APIMonitorData.responses[oldestKey];
        }
        
        if (window.APIMonitorData.config.enableLog) {
            log(`接口响应已存储: ${method} ${url}`, 'success');
            log(`响应状态: ${status}`);
            log(`响应数据: ${JSON.stringify(response).substring(0, 200)}...`);
        }
        
        // 触发自定义事件，通知其他组件
        window.dispatchEvent(new CustomEvent('api-monitor-response', {
            detail: {
                url: url,
                method: method,
                response: response,
                status: status
            }
        }));
    }

    // 设置请求拦截器
    function setRequestInterceptor(interceptor) {
        window.APIMonitorData.requestInterceptor = interceptor;
        log('请求拦截器已设置', 'success');
    }

    // 执行请求拦截器
    function executeRequestInterceptor(request) {
        if (window.APIMonitorData.requestInterceptor && typeof window.APIMonitorData.requestInterceptor === 'function') {
            try {
                return window.APIMonitorData.requestInterceptor(request);
            } catch (error) {
                log(`请求拦截器执行错误: ${error.message}`, 'error');
            }
        }
        return request;
    }

    // 拦截XHR请求
    function interceptXHR() {
        log('开始拦截XHR请求');
        
        const originalXHROpen = XMLHttpRequest.prototype.open;
        const originalXHRSend = XMLHttpRequest.prototype.send;
        
        XMLHttpRequest.prototype.open = function(method, url, ...args) {
            this._apiMonitorMethod = method;
            this._apiMonitorUrl = url;
            
            // 执行请求拦截器
            const request = {
                method: method,
                url: url,
                type: 'xhr'
            };
            executeRequestInterceptor(request);
            
            return originalXHROpen.apply(this, [method, url, ...args]);
        };
        
        XMLHttpRequest.prototype.send = function(...args) {
            const xhr = this;
            const originalOnReadyStateChange = xhr.onreadystatechange;
            
            // 处理请求数据
            if (args.length > 0 && args[0]) {
                const requestData = args[0];
                const request = {
                    method: xhr._apiMonitorMethod,
                    url: xhr._apiMonitorUrl,
                    data: requestData,
                    body: requestData,
                    params: requestData,
                    type: 'xhr'
                };
                executeRequestInterceptor(request);
            }
            
            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {
                    try {
                        const responseText = xhr.responseText;
                        let responseData;
                        
                        // 尝试解析JSON
                        try {
                            responseData = JSON.parse(responseText);
                        } catch (e) {
                            responseData = responseText;
                        }
                        
                        storeApiResponse(xhr._apiMonitorUrl, xhr._apiMonitorMethod, responseData, xhr.status);
                    } catch (e) {
                        log(`XHR响应处理错误: ${e.message}`, 'error');
                    }
                }
                
                if (originalOnReadyStateChange) {
                    originalOnReadyStateChange.apply(xhr, arguments);
                }
            };
            
            return originalXHRSend.apply(this, args);
        };
        
        log('XHR请求拦截器已设置', 'success');
    }

    // 拦截Fetch请求
    function interceptFetch() {
        log('开始拦截Fetch请求');
        
        const originalFetch = window.fetch;
        
        window.fetch = function(input, init) {
            const url = typeof input === 'string' ? input : input.url;
            const method = (init && init.method) || 'GET';
            
            // 执行请求拦截器
            const request = {
                method: method,
                url: url,
                data: init && init.body,
                body: init && init.body,
                params: init && init.body,
                type: 'fetch'
            };
            executeRequestInterceptor(request);
            
            return originalFetch.apply(this, arguments).then(response => {
                // 克隆响应以便读取
                const clonedResponse = response.clone();
                
                clonedResponse.text().then(text => {
                    try {
                        let responseData;
                        
                        // 尝试解析JSON
                        try {
                            responseData = JSON.parse(text);
                        } catch (e) {
                            responseData = text;
                        }
                        
                        storeApiResponse(url, method, responseData, response.status);
                    } catch (e) {
                        log(`Fetch响应处理错误: ${e.message}`, 'error');
                    }
                }).catch(e => {
                    // 即使读取失败，也记录请求信息
                    storeApiResponse(url, method, `读取失败: ${e.message}`, 0);
                });
                
                return response;
            }).catch(error => {
                // 处理网络错误
                storeApiResponse(url, method, `网络错误: ${error.message}`, 0);
                throw error;
            });
        };
        
        log('Fetch请求拦截器已设置', 'success');
    }

    // 监听全局变量变化
    function monitorGlobalVariables() {
        log('开始监听全局变量变化');
        
        // 监听Vue实例
        if (window.Vue) {
            log('检测到Vue框架，开始监听Vue实例');
            
            const originalVueSet = window.Vue.set;
            if (originalVueSet) {
                window.Vue.set = function(obj, key, value) {
                    if (obj && typeof obj === 'object' && key && typeof key === 'string') {
                        log(`Vue数据变化: ${key} = ${JSON.stringify(value).substring(0, 100)}...`);
                    }
                    return originalVueSet.apply(this, arguments);
                };
            }
        }
        
        // 监听React状态变化
        if (window.React) {
            log('检测到React框架，开始监听状态变化');
        }
        
        log('全局变量监听器已设置', 'success');
    }

    // 获取存储的接口数据
    function getApiData() {
        return window.APIMonitorData;
    }

    // 获取特定接口的响应数据
    function getApiResponse(url, method = 'GET') {
        const key = `${method}_${url}`;
        return window.APIMonitorData.responses[key];
    }

    // 监听接口响应事件
    function onApiResponse(callback) {
        window.addEventListener('api-monitor-response', function(event) {
            callback(event.detail);
        });
    }

    // 配置监控选项
    function configure(options) {
        Object.assign(window.APIMonitorData.config, options);
        log('配置已更新', 'success');
    }

    // 清空存储的数据
    function clearData() {
        window.APIMonitorData.responses = {};
        window.APIMonitorData.lastUpdate = null;
        log('数据已清空', 'success');
    }

    // 创建调试面板
    function createDebugPanel(options = {}) {
        const defaultOptions = {
            position: 'top-right',
            width: '400px',
            maxHeight: '500px',
            title: 'API监控面板'
        };
        
        const config = Object.assign({}, defaultOptions, options);
        
        const panel = document.createElement('div');
        panel.id = 'api-monitor-panel';
        panel.style.cssText = `
            position: fixed;
            top: ${config.position.includes('top') ? '10px' : 'auto'};
            bottom: ${config.position.includes('bottom') ? '10px' : 'auto'};
            left: ${config.position.includes('left') ? '10px' : 'auto'};
            right: ${config.position.includes('right') ? '10px' : 'auto'};
            width: ${config.width};
            max-height: ${config.maxHeight};
            background: white;
            border: 1px solid #ccc;
            border-radius: 5px;
            padding: 10px;
            font-size: 12px;
            z-index: 10000;
            overflow-y: auto;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        `;
        
        panel.innerHTML = `
            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
                <h3 style="margin: 0;">${config.title}</h3>
                <div>
                    <button id="api-monitor-clear" style="background: #ffa502; color: white; border: none; padding: 2px 8px; border-radius: 3px; cursor: pointer; margin-right: 5px;">清空</button>
                    <button id="api-monitor-close" style="background: #ff4757; color: white; border: none; padding: 2px 8px; border-radius: 3px; cursor: pointer;">关闭</button>
                </div>
            </div>
            <div id="api-monitor-list" style="max-height: 400px; overflow-y: auto;"></div>
        `;
        
        document.body.appendChild(panel);
        
        // 关闭按钮事件
        document.getElementById('api-monitor-close').addEventListener('click', function() {
            panel.style.display = 'none';
        });
        
        // 清空按钮事件
        document.getElementById('api-monitor-clear').addEventListener('click', function() {
            clearData();
            updatePanel();
        });
        
        // 更新面板内容
        function updatePanel() {
            const apiList = document.getElementById('api-monitor-list');
            const data = getApiData();
            
            let html = '';
            Object.keys(data.responses).forEach(key => {
                const response = data.responses[key];
                html += `
                    <div style="border-bottom: 1px solid #eee; padding: 5px 0;">
                        <div style="font-weight: bold; color: #333;">${response.method} ${response.url}</div>
                        <div style="color: #666; font-size: 11px;">状态: ${response.status} | 时间: ${new Date(response.timestamp).toLocaleTimeString()}</div>
                        <div style="color: #888; font-size: 10px; max-height: 60px; overflow-y: auto; background: #f5f5f5; padding: 3px; margin-top: 3px;">
                            ${JSON.stringify(response.response).substring(0, 200)}...
                        </div>
                    </div>
                `;
            });
            
            if (html === '') {
                html = '<div style="color: #999; text-align: center; padding: 20px;">暂无接口数据</div>';
            }
            
            apiList.innerHTML = html;
        }
        
        // 定期更新面板
        const updateInterval = setInterval(updatePanel, 1000);
        
        // 监听接口响应事件
        onApiResponse(function(data) {
            updatePanel();
        });
        
        // 返回控制对象
        return {
            show: () => panel.style.display = 'block',
            hide: () => panel.style.display = 'none',
            toggle: () => panel.style.display = panel.style.display === 'none' ? 'block' : 'none',
            destroy: () => {
                clearInterval(updateInterval);
                panel.remove();
            },
            update: updatePanel
        };
    }

    // 初始化监控器
    function init(options = {}) {
        log('API监控库开始初始化');
        
        // 应用配置
        if (options.config) {
            configure(options.config);
        }
        
        // 设置拦截器
        interceptXHR();
        interceptFetch();
        monitorGlobalVariables();
        
        log('API监控库初始化完成', 'success');
    }

    // 暴露API到全局
    window.APIMonitorLib = {
        init: init,
        getApiData: getApiData,
        getApiResponse: getApiResponse,
        onApiResponse: onApiResponse,
        configure: configure,
        clearData: clearData,
        createDebugPanel: createDebugPanel,
        setRequestInterceptor: setRequestInterceptor
    };

    // 自动初始化
    init();

    log('API监控库加载完成', 'success');
})(); 